package com.service.impl;

import com.dao.MongodbDao;
import com.dao.ScForStudentDao;
import com.dao.StudentDao;
import com.dto.DTO;
import com.dto.MessageEnum;
import com.entity.*;
import com.exception.CustomException;
import com.exception.SelectCourseFailException;
import com.service.AccountService;
import com.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;
import java.util.Random;

@Service("studentService")
public class StudentServiceImpl implements StudentService, AccountService {
    @Resource
    StudentDao studentDao;
    @Resource(name="scDao")//指定匹配资源  autowired不能指定名字， resource受到先后顺序的影响
    ScForStudentDao scForStudentDao;
    @Resource
    MongodbDao mongodbDao;
    @Override
    public DTO<Student> getAllStudents()  throws Exception{
        List<Student> students = studentDao.getAllStudents();
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  = Optional.ofNullable(students).isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage(),students);
    }

    @Override
    public DTO<Student> selectBySnoWithScs(String sno)  throws Exception{
        Student student = studentDao.selectBySnoWithScs(sno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  = Optional.ofNullable(student).isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage(),null,student);
    }

    @Override
    public DTO<Student> selectBySnoWithClazz(String sno)  throws Exception{
        Student student = studentDao.selectBySnoWithClazz(sno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  = Optional.ofNullable(student).isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage(),null,student);
    }

    @Override
    public DTO<Student> selectBySnoWithScsAndClazz(String sno)  throws Exception{
        System.out.println("---77777777777777----------------");
        System.out.println(mongodbDao);
        Optional<MongoDBDocument> mongoDBDocumentOP = Optional.ofNullable(mongodbDao.findByKey("studentWithAll" + sno, sno, Student.class));

        Student student = mongoDBDocumentOP.isPresent()?(Student)mongoDBDocumentOP.get().getT():null;//1。查询mongodb
        Optional<Student> studentOP = Optional.ofNullable(student);
        Optional<Student> studentResultOP = Optional.ofNullable(null);
        if(!studentOP.isPresent()){//2.如果为空 查询dao mysql
            studentResultOP = Optional.ofNullable(studentDao.selectBySnoWithScsAndClazz(sno));//查询mysql中是否存在
            if(studentResultOP.isPresent()){//3.如果mysql中数据不为空 存monggodb
                System.out.println("存mongodb");
                MongoDBDocument<Student> mongoDBDocument = new MongoDBDocument(sno, studentResultOP.get());
                //将最新的内容录入mongodb
                mongodbDao.save(mongoDBDocument,"studentWithAll"+sno);
            }
        }else{
            studentResultOP = studentOP;
        }
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  = studentResultOP.isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;

       return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage(),studentResultOP.get());
    }

    @Override
    public DTO<Student> selectBySnoWithScsAndCourse(String sno) throws Exception {
        Student student = studentDao.selectBySnoWithScsAndCourse(sno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  = Optional.ofNullable(student).isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage(),null,student);
    }

    @Override
    public DTO<Student> selectBySnoWithClazzANDTeacher(String sno)  throws Exception{
        Student student = studentDao.selectBySnoWithClazzANDTeacher(sno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  = Optional.ofNullable(student).isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage(),null,student);
    }

    @Override
    public DTO<Student> deleteStudentBySno(String sno)  throws Exception{
        Integer result = studentDao.deleteStudentBySno(sno);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  =result> 0?MessageEnum.DELETESTUDENTSUCCESS:MessageEnum.DELETESTUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage());
    }

    @Override
    public DTO<Student> updateStudentBySno(Student student) throws Exception {
        Integer result = studentDao.updateStudentBySno(student);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  =result> 0?MessageEnum.UPDATESTIUDENTSUCCESS:MessageEnum.UPDATESTIUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage());
    }

    @Override
    public DTO<Student> addStudentBySno(Student student) throws Exception {
        Integer result = studentDao.addStudentBySno(student);
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  =result> 0?MessageEnum.ADDSTIUDENTSUCCESS:MessageEnum.ADDSTIUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage());
    }

    /**
     * 学生选课成功 学生成绩加1分，从选课信息中可以获得学生的学号就能查询出学生原来的成绩
     * @param sc
     * @return
     * @throws Exception
     */
    @Override
//事务 ACID 原子性（多条语句要么全部成功要么全部失败） 一致性（数据的变化一致）  隔离性 （锁 同一资源不能同时操作）
// 持久性（一旦提交获取确定取消  永久保存）
    @Transactional(rollbackFor = SelectCourseFailException.class)
    public DTO<Student> addSC(Sc sc) throws Exception {
        Integer result = scForStudentDao.addScByScno(sc);
        if(Math.abs(new Random().nextInt()) % 2 == 0){
            throw new SelectCourseFailException("选课失败");
        }
        System.out.println(sc.getSno()+ " " +sc.getScno()+" "+ sc.getCno()+"     --------222222");
        Student student  = studentDao.selectStudentBySno(sc.getSno());//根据选课记录查询出学生的学号
        System.out.println(student+"     --------33333");
        System.out.println(student.getAvgscore()+"     --------444");
        student.setAvgscore(Optional.ofNullable(student.getAvgscore()).orElse(0f) + 1);//学生原有成绩加1
        studentDao.updateStudentBySno(student);//修改后的学生保存到数据库
        //isPresent表示判断不为空成立则dto为？与：之间的对象
        MessageEnum messageEnum  =result> 0?MessageEnum.ADDSTIUDENTSUCCESS:MessageEnum.ADDSTIUDENTFAIL;
        return new DTO<Student>(messageEnum.getCode(),messageEnum.getMessage());
    }

    @Override
    public DTO<Account> getAccountByAccountName(String accountName) throws Exception {
        DTO<Account> dto = new DTO<Account>();
        Optional<Account> studentOP = Optional.ofNullable(studentDao.getAccountByAccountName(accountName));
        dto.setT(studentOP.get());
        MessageEnum messageEnum = studentOP.isPresent()?MessageEnum.GETSTUDENTSUCCESS:MessageEnum.GETSTUDENTFAIL;
        dto.setCode(messageEnum.getCode());
        dto.setMsg(messageEnum.getMessage());
        return dto;
    }
}
